<template>
    <div id="app">
        <router-view @login="loginDirect" @logout="logoutDirect"></router-view>
    </div>
</template>
<style>
    @import "../static/css/main.css";
    @import "../static/css/color-dark.css"; /*深色主题*/
    /*@import "../static/css/theme-green/color-green.css";   浅绿色主题*/
</style>
<script>
    import * as util from './assets/util.js';
    import userPath from './router/fullpath.js';
    import router from './router'
    import * as params from './store/appServerParams.js'
    import  * as types  from './store/types.js'
    //请求拦截句柄
    let requestInterceptor;
    let reponseInterceptor;
    /*存储请求的数组*/
    let refreshSubscribers = []
    window.isRefreshing = false;


    export default {

        data() {
            return {
                menuData: null,
                userData: null
            }

        },
        methods: {
            getPermission: function (userInfo) {
                let resourcePermission = {};
                if (Array.isArray(userInfo)) {
                    userInfo.forEach(function (e, i) {
                        let key = e;
                        resourcePermission[key] = true;
                    });
                }
                return resourcePermission;
            },
            /*将所有的请求都push到数组中,其实数组是[function(token){}, function(token){},...]*/
            subscribeTokenRefresh: function (cb) {
                refreshSubscribers.push(cb);
            },
            /*数组中的请求得到新的token之后自执行，用新的token去请求数据*/
            onRrefreshed: function (token) {
                refreshSubscribers.map(cb => cb(token));
            },
            checkToken: function () {
                if (util.local(params.TOKEN)) {
                    let now = new Date().getTime();
                    let tokenInfo = util.local(params.TOKENINFO);
                    let time = (now - tokenInfo.createTime) / 1000;
                    if (time > tokenInfo.expireTime && time <= tokenInfo.refreshTime) {
                        return true;//需要刷新
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            },
            setRequestInterceptor: function (resourcePermission) {
                let vm = this;
                requestInterceptor=vm.$http.interceptors.request.use(
                    request => {
                        let perName = request.url.replace(request.baseURL, '').replace('/GET', '').replace('/POST', '').split('?')[0];
                        //权限格式1 /path/${param}
                        request.headers.Authorization = util.local(params.TOKEN);
                        if (params.whiteList.hasOwnProperty(perName) || params.whiteList.hasOwnProperty("/" + perName)) {
                            return request;
                        }
                       if (request.method != "get"&&perName.indexOf("/login")==-1) {
                            if (!resourcePermission[perName] && !resourcePermission["/"+perName]) {
                                //调试信息
                                // console.warn(resourcePermission, config.method + ',' + perName);
                                vm.$message({
                                    message: '无访问权限，请联系企业管理员',
                                    type: 'warning'
                                });
                                //拦截请求
                                return Promise.reject({
                                    message: 'no permission'
                                });
                            }
                        }
                        // request.headers.local = localStorage.local;
                        if (vm.checkToken() && request.url.indexOf('login')==-1 && request.url.indexOf('refreshToken')==-1 ) {

                            if (!window.isRefreshing) {
                                window.isRefreshing = true
                                vm.$http.get("/refreshToken").then(res => {
                                    /*将刷新的token替代老的token*/
                                    request.headers.Authorization = res.data.token;
                                    var tokenInfo = {
                                        token: res.data.token,
                                        createTime: res.data.createTime,
                                        expireTime: res.data.expireTime,
                                        refreshTime: res.data.refreshTime,
                                    }
                                    util.local("tokenInfo",tokenInfo)
                                    // store.commit(types.LOGIN, tokenInfo);
                                    vm.$store.commit(types.REFRESH_WEBSOCKET, true);
                                    window.isRefreshing = false;
                                    /*执行数组里的请求，重新发起被挂起的请求*/
                                    vm.onRrefreshed(res.data.token);
                                    /*执行onRefreshed函数后清空数组中保存的请求*/
                                    refreshSubscribers = [];
                                })
                            }
                            let retry = new Promise((resolve, reject) => {
                                /*(token) => {...}这个函数就是cb*/
                                vm.subscribeTokenRefresh((token) => {
                                    request.headers.Authorization = token;
                                    /*将请求挂起*/
                                    resolve(request)
                                })
                            })
                            return retry

                        } else {
                            return request;
                        }
                    },
                    err => {
                        return Promise.reject(err)
                    }
                )
                console.log('reqNum : ' + requestInterceptor)
            },
            setResponseInterceptor:function(){
                let vm = this;
                reponseInterceptor = vm.$http.interceptors.response.use(
                    response => {
                        return response
                    },
                    error => {
                        if (error.response) {
                            switch (error.response.status) {
                                case 401:
                                    if (error.response.data[params.ERR_KEY_RELOGIN]) {//重新登录
                                        // store.commit(params.LOGOUT);
                                        vm.logoutDirect();
                                        router.replace({
                                            path: '/login',
                                        })
                                    } else if (error.response.data[params.ERR_KEY_NOPERMIT]) {//没有权限
                                        router.replace({
                                            path: '/403',
                                        })
                                    } else {
                                        // store.commit(params.LOGOUT);
                                        vm.logoutDirect();
                                        router.replace({
                                            path: '/login',
                                        })

                                    }
                            }
                        }
                        // console.log(JSON.stringify(error));//console : Error: Request failed with status code 402
                        return Promise.reject(error.response.data)
                    }
                )
            },
            getRoutes: function (userInfo) {
                // if(!userInfo.menus){
                //     return console.warn(userInfo);
                // }
                let vm = this;
                let allowedRouter = [];
                //将菜单数据转成多维数组格式
                let arrayMenus = util.buildMenu(util.convertToJSONList(userInfo));
                util.local(params.AUTH_MENU,arrayMenus);
                //将多维数组转成对象格式
                let hashMenus = {};
                let setMenu2Hash = function (array, base) {
                    array.map(key => {
                        if(key.sysPoId==-1){
                            if (Array.isArray(key.children)) {
                                setMenu2Hash(key.children, key.route);
                            }
                        }else{
                            if (key.url) {
                                let hashKey = ((base ? base + '/' : '') + key.url).replace(/^\//, '');
                                hashMenus['/' + hashKey] = true;
                                if (Array.isArray(key.children)) {
                                    setMenu2Hash(key.children, key.url);
                                }
                            }
                        }

                    });
                };
                setMenu2Hash(arrayMenus);
                //全局挂载hashMenus，用于实现路由守卫
                hashMenus['/login'] = true;
                this.$root.hashMenus = hashMenus;
                //筛选本地路由方法
                let findLocalRoute = function (array, base) {
                    let replyResult = [];
                    array.forEach(function (route) {
                        let pathKey = (base ? base + '/' : '') + route.path;
                        if (hashMenus[pathKey]) {
                            if (Array.isArray(route.children)) {
                                route.children = findLocalRoute(route.children, route.path);
                            }
                            replyResult.push(route);
                        }
                    });
                    if (base) {
                        return replyResult;
                    } else {
                        allowedRouter = allowedRouter.concat(replyResult);
                    }
                }
                let originPath = util.deepcopy(userPath[0].children);
                findLocalRoute(originPath);
                return allowedRouter;
            },
            extendRoutes: function (allowedRouter) {
                let vm = this;
                let actualRouter = util.deepcopy(allowedRouter);
                actualRouter.map(e => {
                    //为动态路由添加独享守卫
                    return e.beforeEnter = function (to, from, next) {
                        if (vm.$root.hashMenus[to.path]) {
                            next()
                        } else {
                            next('/403')
                        }
                    }
                });
                let originPath = util.deepcopy(userPath);
                originPath[0].children = actualRouter;
                //注入路由
                vm.$router.addRoutes(originPath.concat([{
                    path: '*',
                    redirect: '/404'
                }]));
            },
            signin: function (callback) {
                let vm = this;
                //检查登录状态
                let token = util.local(params.TOKEN);

                // alert(location.href)
                if( vm.$router.history.pending!=null ){
                    // let toPath = vm.$router.history.pending.fullPath;
                    let toPath = vm.$router.history.pending.path;
                    // alert( "toPath ::: " + toPath )
                    if( params.whitePageList[toPath]  || params.whitePageList[ "/" +toPath] ){
                        return;
                    }
                }

                if (!token) {
                    return vm.$router.push({path: '/login', query: {from: vm.$router.currentRoute.path}});
                }
                //获取用户信息及权限数据
                let resourceInfo = util.local(params.AUTH_RESOURCE);
                //取得资源权限对象
                let resourcePermission = vm.getPermission(resourceInfo);
                //使用资源权限设置请求拦截
                vm.setRequestInterceptor(resourcePermission);
                vm.setResponseInterceptor();
                //获得实际路由
                let allowedRouter = vm.getRoutes(util.local(params.AUTH_ROUTER));
                //若无可用路由限制访问
                if (!allowedRouter || !allowedRouter.length) {
                    util.local('token', '');
                    return document.body.innerHTML = ('<h1>账号访问受限，请联系系统管理员！</h1>');
                }
                //动态注入路由
                vm.extendRoutes(allowedRouter);
                //保存数据用作他处，非必需
                vm.menuData = allowedRouter;

                //     //执行回调
                typeof callback === 'function' && callback();
            },
            loginDirect: function (newPath) {
                this.signin(() => {
                    this.$router.replace({path: newPath || '/'});
                });
            },
            logoutDirect: function () {
                // 清除session
                util.local('token', '');
                //清除请求权限控制
                this.$http.interceptors.request.eject(requestInterceptor);
                this.$http.interceptors.response.eject(reponseInterceptor);
                //清除菜单权限
                this.$root.hashMenus = {};
                //清除请求头token
                this.$http.defaults.headers.common['Authorization'] = '';
                // 回到登录页
                location.reload(true)
                this.$router.replace({path: '/login'});
            }
        },
        created: function (newPath) {
            this.signin();
        }
    }
</script>
